/******************************************************************************
 * Copyright (C) 2015  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#include "Util.h"
#include <utf8.h>
#include <exception>
#include <sstream>

bool Utf8toWStr(const std::string& _Utf8str, std::wstring& _Wstr)
{
    try
    {
        size_t _Len = utf8::distance(_Utf8str.c_str(), _Utf8str.c_str() + _Utf8str.size());
        _Wstr.resize(_Len);

        if (_Len) {
            utf8::utf8to16(_Utf8str.c_str(), _Utf8str.c_str() + _Utf8str.size(), &_Wstr[0]);
        }
    }
    catch (std::exception)
    {
        _Wstr = L"";
        return false;
    }

    return true;
}

bool Utf8toWStr(char const* _Utf8str, size_t _Csize, wchar_t* _Wstr, size_t& _Wsize)
{
    try
    {
        std::size_t _Len = utf8::distance(_Utf8str, _Utf8str + _Csize);
        if (_Len > _Wsize)
        {
            if (_Wsize > 0) {
                _Wstr[0] = L'\0';
            }
            _Wsize = 0;
            return false;
        }

        _Wsize = _Len;
        utf8::utf8to16(_Utf8str, _Utf8str + _Csize, _Wstr);
        _Wstr[_Len] = L'\0';
    }
    catch (std::exception)
    {
        if (_Wsize > 0) {
            _Wstr[0] = L'\0';
        }
        _Wsize = 0;
        return false;
    }

    return true;
}

bool WStrToUtf8(wchar_t* _Wstr, size_t _Size, std::string& _Utf8str)
{
    try
    {
        std::string _Utf8str2;
        _Utf8str2.resize(_Size * 4);

        char* _Oend = utf8::utf16to8(_Wstr, _Wstr + _Size, &_Utf8str2[0]);
        _Utf8str2.resize(_Oend - (&_Utf8str2[0]));
        _Utf8str = _Utf8str2;
    }
    catch (std::exception)
    {
        _Utf8str = "";
        return false;
    }

    return true;
}

void HexEncodeByteArray(std::uint8_t* _Bytes, std::size_t _Size, std::string& _Result)
{
    std::ostringstream ss;
    for (std::uint8_t _I = 0; _I < _Size; ++_I)
    {
        for (std::uint8_t _J = 0; _J < 2; ++_J)
        {
            unsigned char _Nibble = 0x0F & (_Bytes[_I] >> ((1 - _J) * 4));
            char _EncodedNibble;
            if (_Nibble < 0x0A)
            {
                _EncodedNibble = '0' + _Nibble;
            }
            else
            {
                _EncodedNibble = 'A' + _Nibble - 0x0A;
            }
            ss << _EncodedNibble;
        }
    }
    _Result = ss.str();
}

std::uint32_t GetUInt32ValueFromArray(const Tokens& _Data, std::uint16_t _Index)
{
    if (_Index >= _Data.size()) {
        return 0;
    }
    return (std::uint32_t)atoi(_Data[_Index].c_str());
}